using System;
using System.Collections.Generic;
using Drill.Configuration;
using Drill.Extensibility;

namespace Drill.Core.Builders
{
	public class DrillBitBuilder : IDrillBitBuilder
	{
		private readonly IConfigurationHelper _configurationHelper;
		private readonly IConfigurationSourceSetFactory _configurationSourceSetFactory;
		private readonly string _drillBitName;
		private readonly string _drillBitAssemblyQualifiedTypeName;

		private IList<IConfigurationSource> _configurationSources;
		private IDrillBitInitContext _initContext;
		private IDrillBit _drillBit;

		public DrillBitBuilder(
			string drillBitName,
			string drillBitAssemblyQualifiedTypeName,
			IConfigurationSourceSetFactory configurationSourceSetFactory,
			IConfigurationHelper configurationHelper = null
			)
		{
			if (string.IsNullOrEmpty(drillBitName))
			{
				throw new ArgumentNullException("drillBitName");
			}
			if (string.IsNullOrEmpty(drillBitAssemblyQualifiedTypeName))
			{
				throw new ArgumentNullException("drillBitAssemblyQualifiedTypeName");
			}
			if (null == configurationSourceSetFactory)
			{
				throw new ArgumentNullException("configurationSourceSetFactory");
			}
			_drillBitName = drillBitName;
			_drillBitAssemblyQualifiedTypeName = drillBitAssemblyQualifiedTypeName;
			_configurationSourceSetFactory = configurationSourceSetFactory;
			_configurationHelper = configurationHelper;
		}

		public void BuildConfigurationSources()
		{
			_configurationSources = _configurationSourceSetFactory.CreateConfigurationSources();
		}

		public void BuildInitializationContext()
		{
			_initContext = 
				new DrillBitInitContext
					{
						ConfigurationHelper = _configurationHelper, 
						ConfigurationSources = _configurationSources,
						Name = _drillBitName
					};
		}

		public void CreateDrillBit()
		{
			var activator =
				new ObjectOrFactoryActivator<
						  IDrillBit
						, IDrillBitFactory
						, IDrillBitInitContext>();

			var activatorResult = activator.CreateInstance(_drillBitAssemblyQualifiedTypeName, _initContext);

			// activatorResult.Item1 = IDrillBit
			// activatorResult.Item2 = IDrillBitFactory
			_drillBit =
				(null != activatorResult.Item2)
					? activatorResult.Item2.CreateDrillBit()
					: activatorResult.Item1;
		}

		public IDrillBit GetDrillBit()
		{
			return _drillBit;
		}
	}
}